package com.ruoyi.web.controller.app;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * App端 登录认证
 *
 * @author laoguo
 */
@RestController
@RequestMapping("/app")
public class AppLoginController {

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;


    /**
     * 获取短信验证码 (模拟)
     */
    @PostMapping("/sms/code")
    public AjaxResult getSmsCode(@RequestBody Map<String, String> params) {
        String phonenumber = params.get("phonenumber");
        if (StringUtils.isEmpty(phonenumber)) {
            return AjaxResult.error("手机号码不能为空");
        }

        // --- 模拟生成验证码 ---
        // 实际项目中，这里会调用短信服务商的接口发送验证码
        String verifyCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000)); // 生成6位随机数

        // 将验证码存入Redis，有效期5分钟
        String redisKey = Constants.SMS_CAPTCHA_CODE_KEY + phonenumber;
        redisCache.setCacheObject(redisKey, verifyCode, Constants.SMS_CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

        // 为了方便测试，我们将验证码在返回结果中直接告诉前端
        AjaxResult ajax = AjaxResult.success("验证码发送成功(模拟)");
        ajax.put("mock_code", verifyCode);
        return ajax;
    }

    /**
     * 手机验证码登录
     */
    @PostMapping("/login/sms")
    public AjaxResult smsLogin(@RequestBody Map<String, String> params) {
        String phonenumber = params.get("phonenumber");
        String smsCode = params.get("smsCode");

        if (StringUtils.isAnyBlank(phonenumber, smsCode)) {
            return AjaxResult.error("手机号或验证码不能为空");
        }

        // --- 校验验证码 ---
        String redisKey = Constants.SMS_CAPTCHA_CODE_KEY + phonenumber;
        String cacheCode = redisCache.getCacheObject(redisKey);

        if (cacheCode == null) {
            return AjaxResult.error("验证码已失效，请重新获取");
        }
        if (!cacheCode.equals(smsCode)) {
            return AjaxResult.error("验证码错误");
        }
        // 验证成功后，删除Redis中的验证码，防止重复使用
        redisCache.deleteObject(redisKey);

        // --- 登录或注册用户 ---
        SysUser user = userService.selectUserByUserName(phonenumber);
        if (user == null) {
            // 用户不存在，执行自动注册
            user = new SysUser();
            user.setUserName(phonenumber);
            user.setNickName("用户" + phonenumber.substring(7)); // 默认昵称
            user.setPhonenumber(phonenumber);
            user.setPassword(""); // 手机号登录，密码可以为空或默认值，但需要注意若依密码非空校验
            user.setDeptId(103L); // 可以给一个默认的部门ID
            // **关键：为新用户分配 "小程序用户" 角色**
            Long[] roleIds = {100L}; // 100L 是我们在数据库中为“小程序用户”设定的role_id
            user.setRoleIds(roleIds);

            // 注意：若依默认密码是必填的，我们需要绕过或处理
            // 方案A：在SysUserServiceImpl的insertUser方法中，对手机注册用户设置一个默认加密密码
            // 方案B：直接调用register逻辑，但可能需要伪造密码

            boolean regFlag = userService.registerUser(user);
            if (!regFlag) {
                return AjaxResult.error("注册失败,请联系管理员");
            }
            // 重新查询一次，获取完整的用户信息
            user = userService.selectUserByUserName(phonenumber);
        }

        // --- 生成Token ---
        // --- 【核心修正点】直接为验证通过的用户生成Token ---

        // 1. 将用户信息封装到若依的 LoginUser 对象中
        //    LoginUser 是 Spring Security 用于身份认证的核心对象
        LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));

        // 2. 调用 TokenService 直接创建并返回 Token
        String token = tokenService.createToken(loginUser);

        AjaxResult ajax = AjaxResult.success("登录成功");
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }
}